package ifmo.group5512.timer.modelingClient;

import java.io.*;
import java.net.Socket;

public class ModelingModuleClient {

    private static final String type = "MM";
    private static final String host = "127.0.0.1";

    private Socket s;
    private BufferedReader reader;
    private BufferedWriter writer;


    private Action currentAction = Action.Wait;
    private int time = 0;

    public ModelingModuleClient() {
        init();
    }

    public boolean init() {
        final int port = 18080;
        try {
            s = new Socket(host, port);
            reader = new BufferedReader(new InputStreamReader(s.getInputStream()));
            writer = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));

        } catch (IOException ex) {
            ex.printStackTrace();
            currentAction = Action.CommunicationWasStopped;
            return false;
        }
        currentAction = Action.Wait;
        return true;
    }

    public int getTime() {
        return time;
    }

    public boolean isValid() {
        return currentAction != Action.CommunicationWasStopped;
    }

    public Action lock() {
        if (currentAction != Action.Wait && currentAction != Action.CommunicationWasStopped) {
            return currentAction;
        }

        Action nextAction = communicate(type);
        while (nextAction == Action.Wait) {
            try {
                Thread.sleep(4000);
            } catch (InterruptedException ex) {
                nextAction = Action.CommunicationWasStopped;
                break;
            }

            nextAction = communicate(type);
        }

        return currentAction;
    }

    public Action unlock() {
        if (currentAction == Action.Wait || currentAction == Action.CommunicationWasStopped) {
            return currentAction;
        }

        return communicate(type + "end");
    }

    public Action stopAllSystem() {
        communicate("close");
        return currentAction;
    }

    public void dispose() {
        try {
            s.close();
        } catch (IOException ex) {
            //ignore
        }
        currentAction = Action.CommunicationWasStopped;
    }

    private Action communicate(String command) {

        String answer;

        System.out.println("Socket command: " + command);
        try {
            writer.write(command + '\n');
            writer.flush();

            answer = reader.readLine();
        } catch (IOException ex) {
            System.err.println("CommunicationWasStopped on sending command: " + type + ". Program would be finished.");
            return Action.CommunicationWasStopped;
        }

        currentAction = parseAnswer(answer);
        return currentAction;
    }

    private Action parseAnswer(String answer) {
        if (answer.isEmpty()) {
            return Action.CommunicationWasStopped;
        }

        if ((answer.charAt(0) == '0' && currentAction == Action.Wait)
                || (answer.charAt(0) == '1' && (currentAction == Action.Modeling || currentAction == Action.WritingRequest))) {
            return Action.Wait;
        }

        if (answer.charAt(0) == '1' && currentAction == Action.Wait) {
            String[] arr = answer.split(" ");
            if (arr.length != 3) {
                return Action.CommunicationWasStopped;
            }

            time = Integer.parseInt(arr[1]);
            if (!(arr[2].isEmpty()) && arr[2].charAt(0) == '0') {
                return Action.WritingRequest;
            }

            if (!(arr[2].isEmpty()) && arr[2].charAt(0) == '1') {
                return Action.Modeling;
            }
        }

        return Action.CommunicationWasStopped;
    }
}
